package cn.tedu.mall.order.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.pojo.domain.CsmallAuthenticationInfo;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.order.mapper.OmsOrderItemMapper;
import cn.tedu.mall.order.mapper.OmsOrderMapper;
import cn.tedu.mall.order.service.IOmsCartService;
import cn.tedu.mall.order.service.IOmsOrderItemService;
import cn.tedu.mall.order.service.IOmsOrderService;
import cn.tedu.mall.order.utils.IdGeneratorUtils;
import cn.tedu.mall.pojo.order.dto.OrderAddDTO;
import cn.tedu.mall.pojo.order.dto.OrderItemAddDTO;
import cn.tedu.mall.pojo.order.dto.OrderListTimeDTO;
import cn.tedu.mall.pojo.order.dto.OrderStateUpdateDTO;
import cn.tedu.mall.pojo.order.model.OmsCart;
import cn.tedu.mall.pojo.order.model.OmsOrder;
import cn.tedu.mall.pojo.order.model.OmsOrderItem;
import cn.tedu.mall.pojo.order.vo.OrderAddVO;
import cn.tedu.mall.pojo.order.vo.OrderDetailVO;
import cn.tedu.mall.pojo.order.vo.OrderListVO;
import cn.tedu.mall.product.service.order.IForOrderSkuService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@DubboService
@Service
@Slf4j
public class OmsOrderServiceImpl implements IOmsOrderService {
    //减少库存的功能，是由product模块提供的
    @DubboReference
    private IForOrderSkuService dubboOrderSkuService;

    //购物车中删除选中的商品
    @Autowired
    private IOmsCartService omsCartService;

    //新增订单
    @Autowired
    private OmsOrderMapper omsOrderMapper;

    //新增订单项
    @Autowired
    private OmsOrderItemMapper omsOrderItemMapper;



    @Override
    public OrderAddVO addOrder(OrderAddDTO orderAddDTO) {
        //1.收集订单以及订单项相关的信息
        //1.1 将orderAddDTO转换成OmsOrder对象
        OmsOrder omsOrder = new OmsOrder();
        BeanUtils.copyProperties(orderAddDTO,omsOrder);
        //1.2 收集订单信息
        loadOrder(omsOrder);
        //1.3 收集订单项信息
        List<OrderItemAddDTO> orderItemAddDTOS = orderAddDTO.getOrderItems();
        if (orderItemAddDTOS==null)
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"订单中必须包含订单项");
        //1.4 转换对象类型
        ArrayList<OmsOrderItem> omsOrderItems = new ArrayList<>();
        for (OrderItemAddDTO orderItemAddDTO : orderItemAddDTOS) {
            OmsOrderItem omsOrderItem = new OmsOrderItem();
            BeanUtils.copyProperties(orderItemAddDTO,omsOrderItem);
            //判断属性是否为null
            if (omsOrderItem.getId()==null){
                Long id = IdGeneratorUtils.getDistributeId("order_item");
                omsOrderItem.setId(id);
            }
            if (omsOrderItem.getSkuId()==null){
                throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"订单项必须含有skuId");
            }
            //将omsOrderItem中的orderId赋值为order的id
            omsOrderItem.setOrderId(omsOrder.getId());
            //将omsOrderItem放到omsOrderItems中
            omsOrderItems.add(omsOrderItem);

            //2.操作数据库
            //2.1 减少商品的库存
            Long skuId = omsOrderItem.getSkuId();
            Integer quantity = omsOrderItem.getQuantity();
            int row = dubboOrderSkuService.reduceStockNum(skuId, quantity);
            if (row==0) {
                throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"库存不足");
            }

            //2.2 删除购物车中选中的商品
            OmsCart omsCart = new OmsCart();
            omsCart.setSkuId(skuId);
            omsCart.setUserId(omsOrder.getUserId());
            omsCartService.removeUserCarts(omsCart);
        }

        //2.3 新增订单
        omsOrderMapper.insertOrder(omsOrder);

        //2.4 新增订单项
        omsOrderItemMapper.insertOrderItems(omsOrderItems);

        OrderAddVO orderAddVO = new OrderAddVO();
        orderAddVO.setId(omsOrder.getId());//订单id
        orderAddVO.setSn(omsOrder.getSn());//订单编号
        orderAddVO.setCreateTime(omsOrder.getGmtCreate());//创建时间
        orderAddVO.setPayAmount(omsOrder.getAmountOfActualPay());//获取实际支付金额

        //最后一定要返回VO对象
        return orderAddVO;
    }

    private void loadOrder(OmsOrder omsOrder) {
        //针对order中必须具备，但是没有的属性进行赋值
        //判断id是否为null
        if (omsOrder.getId() == null){
            Long id = IdGeneratorUtils.getDistributeId("order");
            omsOrder.setId(id);
        }
        //判断订单编号是否为null
        if (omsOrder.getSn() == null) {
            //随机生成一个编号
            String sn = UUID.randomUUID().toString();
            omsOrder.setSn(sn);
        }
        //判断user_id 是否为null
        if (omsOrder.getUserId()==null) {
            Long userId = getUserId();
            omsOrder.setUserId(userId);
        }
        //判断订单状态是否为null
        if (omsOrder.getState()==null) {
            omsOrder.setState(0);
        }
        //生成订单时，订单下单时间、数据创建时间、修改时间
        if (omsOrder.getGmtOrder() ==null || omsOrder.getGmtCreate()==null || omsOrder.getGmtModified() ==null ){
            LocalDateTime now = LocalDateTime.now();
            omsOrder.setGmtOrder(now);
            omsOrder.setGmtCreate(now);
            omsOrder.setGmtModified(now);
        }

        //计算支付金额
        //判断商品原价是不是为null
        if (omsOrder.getAmountOfOriginalPrice()==null){
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"订单中必须要原始金额");
        }
        //优惠和运费，如果为null，需要设置值
        if (omsOrder.getAmountOfFreight()==null){
            omsOrder.setAmountOfFreight(new BigDecimal(0.0));
        }

        if (omsOrder.getAmountOfDiscount()==null){
            omsOrder.setAmountOfDiscount(new BigDecimal(0.0));
        }
        //计算实际支付金额 = 原价+运费-优惠
        BigDecimal amountOfOriginalPrice = omsOrder.getAmountOfOriginalPrice();
        BigDecimal amountOfFreight = omsOrder.getAmountOfFreight();
        BigDecimal amountOfDiscount = omsOrder.getAmountOfDiscount();
        BigDecimal actualPrice = amountOfOriginalPrice.add(amountOfFreight).subtract(amountOfDiscount);
        //将实际支付的金额赋值给omsOrder
        omsOrder.setAmountOfActualPay(actualPrice);

    }

    @Override
    public void updateOrderState(OrderStateUpdateDTO orderStateUpdateDTO) {
        //orderStateUpdateDTO 转换成 omsOrder对象
        OmsOrder omsOrder = new OmsOrder();
        BeanUtils.copyProperties(orderStateUpdateDTO,omsOrder);
        omsOrderMapper.updateOrderById(omsOrder);
    }

    @Override
    public JsonPage<OrderListVO> listOrdersBetweenTimes(OrderListTimeDTO orderListTimeDTO) {
        //首先判断时间是否已经提供了startTime和endTime都不为null
        //1.获取开始时间和结束时间
        LocalDateTime startTime = orderListTimeDTO.getStartTime();
        LocalDateTime endTime = orderListTimeDTO.getEndTime();
        if (startTime==null || endTime ==null){
            //赋予默认值
            startTime=LocalDateTime.now().minusMonths(1);
            endTime=LocalDateTime.now();
            orderListTimeDTO.setStartTime(startTime);
            orderListTimeDTO.setEndTime(endTime);
        }else {
            //如果时间都指定了，判断结束时间是否大于开始时间
            if (endTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()
                    <startTime.toInstant(ZoneOffset.of("+8")).toEpochMilli())
                throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"结束时间应该大于开始时间");
        }
        //分页查询
        PageHelper.startPage(orderListTimeDTO.getPage(),orderListTimeDTO.getPageSize());
        List<OrderListVO> orderListVOS = omsOrderMapper.selectOrderByTimes(orderListTimeDTO);
        return JsonPage.restPage(new PageInfo<>(orderListVOS));
    }

    @Override
    public OrderDetailVO getOrderDetail(Long id) {
        return null;
    }

    public CsmallAuthenticationInfo getUserInfo(){
        UsernamePasswordAuthenticationToken authenticationToken =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();

        if (authenticationToken == null) {
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"您当前没有登陆");
        }

        CsmallAuthenticationInfo userInfo = (CsmallAuthenticationInfo) authenticationToken.getCredentials();
        return userInfo;
    }

    public Long getUserId(){
        return getUserInfo().getId();
    }
}
